package main

import "fmt"

/*
常量使用介绍

相对于变量，常量是恒定不变的值，常量是一个简单值的标识符，在程序运行时不会被修改。所以常量在定义的时候必须赋值。

TIPS：
	· 常量中的数据类型只可以是布尔型、数字型（整型、浮点型和复数型）和字符串；
	· 常量定义后未被使用，不会在编译时报错。而变量定义后未被使用会在编译时报错
*/
func main() {

	/*
		一. 声明方式：const 标识符 [类型] = 值

		TIPS：可以省略类型说明符[type]，因为编译器可以根据变量的值来自动推断其类型
	*/
	const A string = "steven"
	fmt.Println(A)
	const B = "STEVEN"
	fmt.Println(B)
	const C = "我是常量，未使用但是不会报错"

	// 给常量赋值会报'cannot assign to ...' 的错误
	// C = "我是常量，不能被修改"

	/*
		二. 用于枚举
	*/
	fmt.Println(AA, BB, CC)
	fmt.Printf("在常量组中如果不指定类型和初始值，则与上一行非空常量的值相同。DD, FF, GG, HH: %d %d %d %d \n", DD, FF, GG, HH)

	/*
		三. iota：特殊的常量值，是一个系统定义的可以被编译器修改的常量值。

			TIPS：iota只能被用在常量的赋值中，在每一个const关键字出现时被重置为0，然后每出现一个常量，iota所代表的数值会自动增加1。iota可以
				  理解成常量组中常量的计数器，不论该常量的值是什么，只要有一个常量，那么iota就加1
	*/
	const HHH = iota
	fmt.Printf("HHH：%d \n", HHH)
	const III = iota
	fmt.Printf("III：%d  \n", III)
	fmt.Printf("在常量组中，第一个iota等于0，每当iota在新的一行被使用时，它的值都会自动加1。II, JJ, KK: %d %d %d \n", II, JJ, KK)

	fmt.Printf("使用_跳过某些值。L, M, N, NN, OO, PP: %d %d %s %s %d %d \n", L, M, N, NN, OO, PP)

	fmt.Printf("iota声明中间插队。O, P, Q, R：%d %d %d %d \n", O, P, Q, R)

	fmt.Printf("定义数量级。KB, MB, GB, TB, PB：%d %d %d %d %d \n", KB, MB, GB, TB, PB)

	fmt.Printf("多个iota定义在一行。a, b, c, d, e, f：%d %d %d %d %d %d \n", a, b, c, d, e, f)
}

/*
常量组实现枚举功能
*/
const (
	AA = 1
	BB = 2
	CC = 3
)

/*
在常量组中如果不指定类型和初始值，则与上一行非空常量的值相同
*/
const (
	DD = 10
	FF
	GG
	HH
)

/*
在常量组中，第一个iota等于0，每当iota在新的一行被使用时，它的值都会自动加1
*/
const (
	II = iota
	JJ = iota
	KK = iota
)

/*
使用_跳过某些值
*/
const (
	L = iota
	M
	_
	NN = "我是字符串"
	N
	OO = iota
	PP
)

/*
iota声明中间插队
*/
const (
	O = iota
	P = 100
	Q = iota
	R
)

/*
定义数量级
*/
const (
	_  = iota
	KB = 1 << (10 * iota)
	MB = 1 << (10 * iota)
	GB = 1 << (10 * iota)
	TB = 1 << (10 * iota)
	PB = 1 << (10 * iota)
)

/*
多个iota定义在一行
*/
const (
	a, b = iota + 1, iota + 2 //1,2
	c, d                      //2,3
	e, f                      //3,4
)
